/**
 * 报表设计公司(2011)
 */
package com.reportgear.report.view.grid.selection;

import net.abbp.report.model.Cell;

/**
 * 单元格选择集
 * 
 * @version 1.0 2011-3-14
 * @author <a herf="lexloo@gmail.com">lexloo</a>
 * @since ANNCSR 2.0
 * 
 */
public class Selection {
	// 起始列
	private int column = 0;
	// 列是否无限
	private boolean columnEndless = false;
	// 列跨度
	private int columnSpan = 1;
	// 起始行
	private int row = 0;
	// 行是否无限
	private boolean rowEndless = false;
	// 行跨度
	private int rowSpan = 1;

	public String toString() {
		return "column:" + this.column + ",row:" + this.row + ",columnSpan:" + this.columnSpan + ",rowSpan:"
				+ this.rowSpan + ",columnEndless:" + this.columnEndless + ",rowEndless:" + this.rowEndless;
	}

	/**
	 * 构造器
	 */
	public Selection() {

	}

	/**
	 * 通过单元格构造
	 * 
	 * @param cell
	 */
	public Selection(Cell cell) {
		this(cell.getColumn(), cell.getRow(), cell.getColumnSpan(), cell.getRowSpan());
	}

	/**
	 * 构造器
	 * 
	 * @param column
	 *            列
	 * @param row
	 *            行
	 */
	public Selection(int column, int row) {
		this(column, row, 1, 1);
	}

	/**
	 * 构造器
	 * 
	 * @param column
	 *            列
	 * @param row
	 *            行
	 * @param columnSpan
	 *            列跨度
	 * @param rowSpan
	 *            行跨度
	 */
	public Selection(int column, int row, int columnSpan, int rowSpan) {
		this();
		this.setBounds(column, row, columnSpan, rowSpan);
	}

	public Selection(Selection s) {
		this(s.column, s.row, s.columnSpan, s.rowSpan);
	}

	/**
	 * 选择集中是否包含指定行列
	 * 
	 * @param column
	 *            列
	 * @param row
	 *            行
	 * @return 是否包含
	 */
	public boolean contains(int column, int row) {
		final int h = this.row + this.rowSpan;
		final int w = this.column + this.columnSpan;

		if (this.rowEndless && this.columnEndless) {
			return true;
		} else if (this.rowEndless) {
			if (column >= this.column && column < w) {
				return true;
			}
		} else if (this.columnEndless) {
			if (row >= this.row && row < h) {
				return true;
			}
		} else {
			if (row >= this.row && row < h && column >= this.column && column < w) {
				return true;
			}
		}

		return false;
	}

	public boolean contains(int X, int Y, int W, int H) {
		int w = this.columnSpan;
		int h = this.rowSpan;
		if ((w | h | W | H) < 0) {
			return false;
		}
		final int x = this.column;
		final int y = this.row;
		if (X < x || Y < y) {
			return false;
		}
		w += x;
		W += X;
		if (W <= X) {
			if (w >= x || W > w) {
				return false;
			}
		} else {
			if (w >= x && W > w) {
				return false;
			}
		}
		h += y;
		H += Y;
		if (H <= Y) {
			if (h >= y || H > h) {
				return false;
			}
		} else {
			if (h >= y && H > h) {
				return false;
			}
		}
		return true;
	}

	public boolean contains(Selection s) {
		return this.contains(s.column, s.row, s.columnSpan, s.rowSpan);
	}

	/**
	 * 
	 * @return 起始列
	 */
	public int getColumn() {
		return this.column;
	}

	/**
	 * 
	 * @return 列跨度
	 */
	public int getColumSpan() {
		return this.columnSpan;
	}

	/**
	 * 
	 * @return 起始行
	 */
	public int getRow() {
		return this.row;
	}

	/**
	 * 
	 * @return 行跨度
	 */
	public int getRowSpan() {
		return this.rowSpan;
	}

	public boolean intersects(Selection s) {
		int tw = this.columnSpan;
		int th = this.rowSpan;
		int rw = s.columnSpan;
		int rh = s.rowSpan;
		if (rw <= 0 || rh <= 0 || tw <= 0 || th <= 0) {
			return false;
		}
		final int tx = this.column;
		final int ty = this.row;
		final int rx = s.columnSpan;
		final int ry = s.rowSpan;
		rw += rx;
		rh += ry;
		tw += tx;
		th += ty;

		return ((rw < rx || rw > tx) && (rh < ry || rh > ty) && (tw < tx || tw > rx) && (th < ty || th > ry));
	}

	/**
	 * 
	 * @return 列是否无限
	 */
	public boolean isColumnEndless() {
		return this.columnEndless;
	}

	/**
	 * 
	 * @return 行是否无限
	 */
	public boolean isRowEndless() {
		return this.rowEndless;
	}

	/**
	 * 设置属性
	 * 
	 * @param column
	 *            列
	 * @param row
	 *            行
	 * @param columnSpan
	 *            列跨度
	 * @param rowSpan
	 *            行跨度
	 */
	public void setBounds(int column, int row, int columnSpan, int rowSpan) {
		this.column = column;
		this.row = row;
		this.columnSpan = columnSpan;
		this.rowSpan = rowSpan;
	}

	/**
	 * 设置起始列
	 * 
	 * @param column
	 *            值
	 */
	public void setColumn(int column) {
		this.column = column;
	}

	/**
	 * 设置列是否无限
	 * 
	 * @param columnEndless
	 *            值
	 */
	public void setColumnEndless(boolean columnEndless) {
		this.columnEndless = columnEndless;
	}

	/**
	 * 设置列跨度
	 * 
	 * @param columSpan
	 *            值
	 */
	public void setColumSpan(int columSpan) {
		this.columnSpan = columSpan;
	}

	/**
	 * 设置起始行
	 * 
	 * @param row
	 *            值
	 */
	public void setRow(int row) {
		this.row = row;
	}

	/**
	 * 设置行是否无限
	 * 
	 * @param rowEndless
	 *            值
	 */
	public void setRowEndless(boolean rowEndless) {
		this.rowEndless = rowEndless;
	}

	/**
	 * 设置行跨度
	 * 
	 * @param rowSpan
	 *            值
	 */
	public void setRowSpan(int rowSpan) {
		this.rowSpan = rowSpan;
	}

	public Selection union(Selection s) {
		long tx2 = this.columnSpan;
		long ty2 = this.rowSpan;
		if ((tx2 | ty2) < 0) {
			return new Selection(s);
		}
		long rx2 = s.columnSpan;
		long ry2 = s.rowSpan;
		if ((rx2 | ry2) < 0) {
			return new Selection(this);
		}
		int tx1 = this.column;
		int ty1 = this.row;
		tx2 += tx1;
		ty2 += ty1;
		final int rx1 = s.column;
		final int ry1 = s.row;
		rx2 += rx1;
		ry2 += ry1;
		if (tx1 > rx1) {
			tx1 = rx1;
		}
		if (ty1 > ry1) {
			ty1 = ry1;
		}
		if (tx2 < rx2) {
			tx2 = rx2;
		}
		if (ty2 < ry2) {
			ty2 = ry2;
		}
		tx2 -= tx1;
		ty2 -= ty1;
		if (tx2 > Integer.MAX_VALUE) {
			tx2 = Integer.MAX_VALUE;
		}
		if (ty2 > Integer.MAX_VALUE) {
			ty2 = Integer.MAX_VALUE;
		}
		return new Selection(tx1, ty1, (int) tx2, (int) ty2);
	}
}
